package dancereal;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class J02_Departments {

	/* 1.JDBC 드라이버 불러오기
	 * JDBC 드라이버는 데이터베이스에 연결해야 할
	 * 필요가 있는 자바 클래스와 JDBC 드라이버 사이의 
	 * 계약을 정의하는 인터페이스들을 구현한 것
	 * 드라이버는 jar 파일 형태로 배포
	 * 
	 * JDBC 드라이버를 불러오는 방법에는
	 * 수동 MANUAL과 동적 DYNAMIC이 있음
	 * Class.forName("oracle.jdbc.driver.OracleDriver");
	 * Class.forName(DRV);
	 * 
	 * forName 메서드는 ClassNotFoundException
	 * 예외를 던지기 때문에 try - catch 블럭안에 둬야함
	 * 
	 * 2.데이터베이스 연결하기
	 * Connection 인터페이스는 데이터베이스
	 * 연결객체를 위한 그릇(템플릿)임
	 * 연결객체를 얻으려면 DriverManager클래스의
	 * getConnection 메서드를 이용
	 * getConnection 메서드는 앞의 과정에서
	 * 메모리에 올려둔 드라이버를 찾고 
	 * URL, USR, PWD를 통해 데이터베이스 서버에 
	 * 연결을 하고 그 결과를 Connection 으로 반환
	 * 
	 * JDBC 연결시 사용하는 URL은 다음과 같음
	 * jdbc:프로토콜:하위이름
	 * jdbc:oracle:this:@주소:포트:DB이름?user=아이디&password=비밀번호
	 * jdbc:mysql://주소/DB이름?user=아이디&amp password=비밀번호
	 * 
	 * 3.SQL 질의문 생성 및 실행
	 * Statement, PreparedStatement 객체는
	 * 실행할 SQL 질의문을 의미함
	 * createStatement, preparedStatement 메서드를
	 * 이용해서 위 객체를 얻을 수 있음
	 * 단, 위 메서드를 호출할때는 생성 SQL 질의문을
	 * 인자로 전달해야 함
	 * 생성한 객체를 실행하려면 executeQuery나 
	 * executeUpdate 메서드를 이용함
	 * executeQuery : SQL 질의문이 select 인 경우
	 * executeUpdate : insert,update,delete 
	 * 				   create,alter,drop 인 경우
	 * 
	 * executeUpdate의 실행결과는 질의문에 의해
	 * 변경된 레코드 수나 0을 반환
	 * executeQuery의 실행결과는 질의문에 의해
	 * 생성된 데이터를 담아두는 ResultSet 객체를 반환
	 * 단, 생성된 데이터가 없는 경우 null 은 아님
	 * 
	 * Statement 에서 파생된 PreparedStatement는
	 * Statement 의 인기있는 대체제임
	 * SQL 문을 미리 컴파일하고 저장해두기 때문에
	 * 추후 동일한 SQL문을 실행할 경우
	 * 빠르게 처리 할 수 있는 장점이 제공
	 * 
	 * 4. 결과 집합 객체 다루기
	 * 결과집합은 Statement, PreparedStatement에서
	 * 반환된 데이터베이스 테이블을 의미함
	 * 결과집합 객체는 현재데이터 행을 가리키는 
	 * 커서를 가지고 있음
	 * 커서는 처음에는 테이블을 가리키고 있다가
	 * next 메서드가 호출되면 다음 레코드로 
	 * 이동하고 true 또는 false 를 반환함
	 * true 가 반환되면 현재 레코드가 존재한다는 의미
	 * false 가 반환되면 더이상 레코드가 없다는 의미
	 * while 을 이용해서 레코드에 접근할 수 있음
	 * 
	 * next 메서드로 레코드에 접근한 뒤, 각 필드 값을
	 * 가져오려면 getXxx 메서드를 사용해야 함
	 * 일반적으로 필드 값을 문자열로 가져오는
	 * getString 메서드를 많이 사용
	 * 필드값을 int 로 가져오려면 getInt를 사용하면 됨
	 * 
	 * 필드값은 필드이름 또는 필드 위치값을
	 * 인자로 전달해서 필드값을 가져올 수 있음
	 * getString(1)
	 * getString("department_id")
	 * 
	 * 5. JDBC 객체 닫기
	 * 모든 JDBC 객체는 사용한 후 그들의 
	 * close 메서드를 호출해서 항상 닫아야 함
	 * try{
	 * 		... ...
	 * 		... ...	
	 * 		rs.close();
	 * 		pstmt.close();
	 * 		conn.close();
	 * }catch (Exception ex){
	 * 		ex.printStackTrace();
	 * 
	 * 위 코드는 완벽하지 않음
	 * pstmt.close(); 가 실패하는 경우,
	 * 그 아래 코드는 실행되지 않기 때문임
	 * 따라서, close 관련 코드는 finally 절에 작성해야 함 (finally 는 꼭 실행함)
	 * 즉, 예외가 발생하든 하지 않든 간에 
	 * 무조건 실행되어야 하는 코드는 finally 절에
	 * 작성하면 프로그램이 완벽해짐
	 * 
	 * 
	 */
	public static void main(String[] args) {
	final String DRV = "oracle.jdbc.driver.OracleDriver";
	final String URL = "jdbc:oracle:thin:@112.216.253.125:1521:xe";
	final String USR = "realdance";
	final String PWD = "realdance";
	
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	String SQL = "select * from departments";
	
	try{
		Class.forName(DRV);
		conn = DriverManager.getConnection(URL, USR, PWD);
		pstmt = conn.prepareStatement(SQL);
		rs = pstmt.executeQuery();
		if(rs.next()){
			do{
				System.out.println(rs.getString("department_id"));
				
			}while(rs.next());
		}else{
				System.out.println("데이터가 음씀");
			}
		
		
	}catch(Exception e){
		e.printStackTrace();
	}finally{
		if(rs != null)
			try{rs.close();	rs = null;}	
	catch(Exception e){}{
		if(pstmt != null)
			try{pstmt.close(); pstmt = null;}
	catch(Exception e){}{
		if(conn != null)
			try{conn.close(); conn = null;}
		catch(Exception e){}
		
	}
	}
	}	
	}

}
